﻿using System;
using System.Linq;
using System.Threading.Tasks;
using System.Web.Http;
using Autofac;
using Newtonsoft.Json.Linq;
using Pay.Core;
using Pay.DTO;
using Pay.IService;
using Pay.Service;
using Pay.TO;
using System.Collections.Generic;
using Pay.Core.WeiXin;
using System.Web;
using Pay.DTO.htl;
using Pay.DTO.hniao;
using System.Net.Http;
using System.Threading;
using System.Collections.Specialized;

namespace Pay.Api.Controllers
{
    /// <summary>
    /// 扫码支付
    /// </summary>
    public partial class OpenController : BaseController
    {
        /// <summary>
        /// 商城支付
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        protected async Task<mall_result> MallPay(mall_model model)
        {
            if (model.type == 0) model.type = 3;
            if (string.IsNullOrEmpty(model.order_no))
                return ApiResultToJson.Json<mall_result>("订单号不能为空");
            else
            {
                if (model.order_no.Length < 13)
                    return ApiResultToJson.Json<mall_result>("订单号最小14位");
                if (model.order_no.Length > 31)
                    return ApiResultToJson.Json<mall_result>("订单号最大长度30位");
            }
            if (string.IsNullOrEmpty(model.tran_amount))
                return ApiResultToJson.Json<mall_result>("交易金额不能为空");
            if (string.IsNullOrEmpty(model.pay_code))
                return ApiResultToJson.Json<mall_result>("支付方式不能为空");
            if (string.IsNullOrEmpty(model.notify))
                return ApiResultToJson.Json<mall_result>("支付成功后服务器回调该地址不能为空");
            if (model.pay_channel == PayChannel.None)
                return ApiResultToJson.Json<mall_result>("通道不能为空");
            model.pay_type = PayType.Native;
            if (model.pay_code == "WXPAY_APP")
                model.pay_type = PayType.SDK;
            else if (model.pay_code == "WXPAY_JS" || model.pay_code == "ALIPAY_JS")
                model.pay_type = PayType.JSPAY;
            else if (model.pay_code == "ALIPAY_APP")
            {
                model.pay_type = PayType.SDK;
                model.pay_channel = PayChannel.AliPay;
            }
            //把商户请求转为通道请求消息
            var _iPayService = _iocContext.ResolveKeyed<IPayService>(model.pay_channel);
            var data = await _iPayService.MallPay(model);
            return data;
        }
        /// <summary>
        /// 商城支付异步回调通知
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [Route("mall_notify/{id}"), HttpPost, HttpGet, AllowAnonymous]
        public async Task<string> MallNotify(string id)
        {
            var log = IocHelper.Get<ILogHelper>("info");
            log.Info("sfb-商城支付异步通知了:" + id);
            //校验第三方返回请求验证数据
            var payment = new payment_query { key = "e590999272769b5d0e78726848f99ad7" };
            ResponseHandler resHandler = new ResponseHandler(null);
            string return_code = resHandler.GetParameter("return_code");
            string return_msg = resHandler.GetParameter("return_msg");
            resHandler.SetKey(payment.key);
            if (resHandler.IsTenpaySign())
            {
                var pay_no = resHandler.GetParameter("out_trade_no");
                log.Info("sfb异步通知成功:" + pay_no);
                string transaction_no = resHandler.GetParameter("transaction_id");
                var pay_html = _iPayHtmlService.Get(id);
                if (pay_html == null)
                {
                    log.Info("sfb-保存数据库订单失败:" + pay_no);
                    return "<xml><return_code><![CDATA[fail]]></return_code></xml>";
                }
                if (return_code == "SUCCESS")
                {
                    string time_end = resHandler.GetParameter("time_end");
                    DateTime pay_time = time_end.ToDateTime();
                    int result = _iOrderService.PaySuceess(pay_html, transaction_no, pay_time);
                    if (result > 0)
                    {
                        var charge = pay_html.charge.ToObject<charge_dto>();
                        var _iPayService = _iocContext.ResolveKeyed<IPayService>(charge.pay_info.pay_channel);
                        var notifyResult = await _iPayService.Notify(charge.merchant_no, charge.order_no);
                        if (notifyResult != "OK")
                        {
                            //创建通知消息对象
                            _iPayNotifyService.Save(new pay_notify_dto
                            {
                                merchant_no = charge.merchant_no,
                                order_no = charge.order_no,
                                pay_channel = charge.pay_info.pay_channel,
                                type = 1,
                                status = 2,
                                create_time = DateTime.Now
                            });
                        }
                        _iPayHtmlService.Remove(id);
                    }
                    //回执成功，通道不会再通知
                    if (result > 0)
                    {
                        return "<xml><return_code><![CDATA[SUCCESS]]></return_code></xml>";
                    }
                    return "<xml><return_code><![CDATA[fail]]></return_code></xml>";
                }
                else
                {
                    var result = _iChargeService.PayFail(pay_html, transaction_no, return_msg);
                    log.Info("sfb-微信执行失败:" + pay_no);
                    return "<xml><return_code><![CDATA[fail]]></return_code></xml>";
                }
            }
            else
            {
                log.Info("sfb-签名不正确:" + id);
                return "<xml><return_code><![CDATA[签名不正确]]></return_code></xml>";
            }
        }
        /// <summary>
        /// 支付补单
        /// </summary>
        /// <param name="id"></param>
        /// <param name="payNo"></param>
        /// <returns></returns>
        [Route("mall_replay_notify"), HttpGet, HttpPost, AllowAnonymous]
        public async Task<string> MallReplayNotify(string id, string payNo)
        {
            var log = IocHelper.Get<ILogHelper>("info");
            var pay_html = _iPayHtmlService.Get(id);
            if (pay_html == null)
            {
                log.Info("sfb-保存数据库订单失败:" + payNo);
                return "<xml><return_code><![CDATA[fail]]></return_code></xml>";
            }
            int result = _iOrderService.PaySuceess(pay_html, payNo, DateTime.Now);
            if (result > 0)
            {
                var charge = pay_html.charge.ToObject<charge_dto>();
                var _iPayService = _iocContext.ResolveKeyed<IPayService>(charge.pay_info.pay_channel);
                var notifyResult = await _iPayService.Notify(charge.merchant_no, charge.order_no);
                if (notifyResult != "OK")
                {
                    //创建通知消息对象
                    _iPayNotifyService.Save(new pay_notify_dto
                    {
                        merchant_no = charge.merchant_no,
                        order_no = charge.order_no,
                        pay_channel = charge.pay_info.pay_channel,
                        type = 1,
                        status = 2,
                        create_time = DateTime.Now
                    });
                }
                _iPayHtmlService.Remove(id);
            }
            //回执成功，通道不会再通知
            if (result > 0)
            {
                return "<xml><return_code><![CDATA[SUCCESS]]></return_code></xml>";
            }
            return "<xml><return_code><![CDATA[fail]]></return_code></xml>";
        }

        /// <summary>
        /// 开联通网关支付异步通知
        /// </summary>
        /// <returns>The pay notify.</returns>
        [Route("klt_notify"), HttpPost, HttpGet, AllowAnonymous]
        public async Task<string> KltPayNotify([FromBody] klt_gateway_notify model)
        {
            var log = IocHelper.Get<ILogHelper>("info");
            log.Info("klt-商城支付异步通知了:" + model.ToJson());
            var kltDataSign = new kltPaySign();
            var srcMsg = kltDataSign.SrcMsg(model);
            if (kltDataSign.VerifySign(srcMsg, model.signMsg, RequestMethod.KLT_PAY_SECRET_URL, false))
            {
                log.Info("klt异步通知成功,开联订单号：" + model.mchtOrderId);
                var pay_html = _iPayHtmlService.Get(model.ext1);
                if (pay_html == null)
                {
                    log.Info("klt-获取html订单失败");
                    return "fail";
                }
                if (model.payResult.Equals("1"))
                {
                    DateTime pay_time = model.payDatetime.ToDateTime();
                    string transaction_no = model.mchtOrderId;
                    int result = _iOrderService.PaySuceess(pay_html, transaction_no, pay_time);
                    if (result > 0)
                    {
                        var charge = pay_html.charge.ToObject<charge_dto>();
                        var _iPayService = _iocContext.ResolveKeyed<IPayService>(charge.pay_info.pay_channel);
                        var notifyResult = await _iPayService.Notify(charge.merchant_no, charge.order_no);
                        if (notifyResult != "OK")
                        {
                            //创建通知消息对象
                            _iPayNotifyService.Save(new pay_notify_dto
                            {
                                merchant_no = charge.merchant_no,
                                order_no = charge.order_no,
                                pay_channel = charge.pay_info.pay_channel,
                                type = 1,
                                status = 2,
                                create_time = DateTime.Now
                            });
                        }
                        _iPayHtmlService.Remove(model.ext1);
                        //todo:生成订单支付成功xml脚本，用于上传电子口岸三单对接。
                        return "success";
                    }
                    return "fail:订单业务处理失败";
                }
                return "fail:支付失败";
            }

            return "fail:签名失败";
        }


        /// <summary>
        /// 拓垦用户升级支付
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        protected async Task<native_result> TokenUserUpgradePay(native_model model)
        {
            if (model.type == 0) model.type = 2;
            if (string.IsNullOrEmpty(model.order_no))
                return ApiResultToJson.Json<native_result>("订单号不能为空");
            else
            {
                if (model.order_no.Length < 13)
                    return ApiResultToJson.Json<native_result>("订单号最小14位");
                if (model.order_no.Length > 31)
                    return ApiResultToJson.Json<native_result>("订单号最大长度30位");
            }
            if (string.IsNullOrEmpty(model.tran_amount))
                return ApiResultToJson.Json<native_result>("交易金额不能为空");
            if (string.IsNullOrEmpty(model.pay_code))
                return ApiResultToJson.Json<native_result>("支付方式不能为空");
            if (string.IsNullOrEmpty(model.notify))
                return ApiResultToJson.Json<native_result>("支付成功后服务器回调该地址不能为空");
            if (model.pay_channel == PayChannel.None)
                return ApiResultToJson.Json<native_result>("通道不能为空");
            model.pay_type = PayType.Native;
            if (model.pay_code == "WXPAY_APP")
                model.pay_type = PayType.SDK;
            else if (model.pay_code == "WXPAY_JS" || model.pay_code == "ALIPAY_JS")
                model.pay_type = PayType.JSPAY;
            //把商户请求转为通道请求消息
            var _iPayService = _iocContext.ResolveKeyed<IPayService>(model.pay_channel);
            var data = await _iPayService.NativePay(model);
            return data;
        }
        /// <summary>
        /// 拓垦用户升级支付异步回调通知
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [Route("Token_user_upgrade_notify/{id}"), HttpPost, HttpGet, AllowAnonymous]
        public string TokenUserUpgradeNotify(string id)
        {
            var log = IocHelper.Get<ILogHelper>("info");
            log.Info("h5支付异步回调通知...");
            ResponseHandler payNotifyRepHandler = new ResponseHandler(null);
            payNotifyRepHandler.SetKey(TenPayV3Info.Key);
            string attach = payNotifyRepHandler.GetParameter("attach");
            string return_code = payNotifyRepHandler.GetParameter("return_code");
            string return_msg = payNotifyRepHandler.GetParameter("return_msg");
            string xml = string.Format(@"<xml><return_code><![CDATA[{0}]]></return_code><return_msg><![CDATA[{1}]]></return_msg></xml>", return_code, return_msg);
            log.Info("return_code:" + return_code + ",attach=" + attach);
            if (return_code.ToUpper() != "SUCCESS")
            {
                return xml;
            }

            string out_trade_no = payNotifyRepHandler.GetParameter("out_trade_no");
            string transaction_id = payNotifyRepHandler.GetParameter("transaction_id");
            log.Info("out_trade_no:" + out_trade_no + ",transaction_id：" + transaction_id);
            if (payNotifyRepHandler.IsTenpaySign())
            {
                var pay_no = out_trade_no;
                log.Info("拓垦用户升级支付异步通知成功:" + pay_no);
                string transaction_no = transaction_id;
                var pay_html = _iPayHtmlService.Get(id);
                if (pay_html == null)
                {
                    log.Info("拓垦用户升级-保存数据库订单失败:" + pay_no);
                    return string.Format(@"<xml><return_code><![CDATA[{0}]]></return_code><return_msg><![CDATA[{1}]]></return_msg></xml>", return_code, return_msg);
                }
                if (return_code == "SUCCESS")
                {
                    lock (jwuctLock)
                    {
                        string time_end = payNotifyRepHandler.GetParameter("time_end");
                        DateTime pay_time = time_end.ToDateTime();
                        var charge = pay_html.charge.ToObject<charge_dto>();
                        charge.amount = charge.pay_amount;
                        charge.status = ChargeStatus.Finish;
                        charge.pay_info.transaction_no = transaction_id;
                        charge.pay_info.pay_time = pay_time;
                        charge = _iChargeService.AddByTokenUserUpgradePay(charge);
                        _iTokenBillService.CreateTokenBill(charge.bind_id.Value, charge.profit);
                        //将用户升级成创客
                        var result = _iTokenUserService.TokenUpgradeMaker((long)charge.bind_id);
                        //回执成功，通道不会再通知
                        if (result)
                        {
                            return string.Format(@"<xml><return_code><![CDATA[{0}]]></return_code><return_msg><![CDATA[{1}]]></return_msg></xml>", return_code, return_msg);
                        }
                    }
                    return string.Format(@"<xml><return_code><![CDATA[{0}]]></return_code><return_msg><![CDATA[{1}]]></return_msg></xml>", return_code, return_msg);
                }
                else
                {
                    var result = _iChargeService.PayFail(pay_html, transaction_no, return_msg);
                    log.Info("拓垦用户升级支付-微信执行失败:" + pay_no);
                    return string.Format(@"<xml><return_code><![CDATA[{0}]]></return_code><return_msg><![CDATA[{1}]]></return_msg></xml>", return_code, return_msg);
                }
            }
            else
            {
                log.Info("拓垦用户升级支付-签名不正确:" + id);
                return string.Format(@"<xml><return_code><![CDATA[{0}]]></return_code><return_msg><![CDATA[{1}]]></return_msg></xml>", return_code, return_msg);
            }
        }

        /// <summary>
        /// 模拟升级支付成功
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [Route("token_upgrade_pay_success/{id}"), HttpPost, HttpGet, AllowAnonymous]
        public string TokenUpgradePaySuccess(string id)
        {
            string transaction_no = "89900000";
            var pay_html = _iPayHtmlService.Get(id);
            if (pay_html == null)
            {

                return "<xml><return_code><![CDATA[fail]]></return_code></xml>";
            }
            DateTime pay_time = DateTime.Now;
            var charge = pay_html.charge.ToObject<charge_dto>();
            charge.status = ChargeStatus.Finish;
            charge.amount = charge.pay_amount;
            charge.pay_info.transaction_no = transaction_no;
            charge.pay_info.pay_time = pay_time;
            charge = _iChargeService.AddByTokenUserUpgradePay(charge);
            _iTokenBillService.CreateTokenBill(charge.bind_id.Value, charge.profit);
            //将用户升级成创客
            var result = _iTokenUserService.TokenUpgradeMaker((long)charge.bind_id);

            //回执成功，通道不会再通知
            if (result)
            {
                return "<xml><return_code><![CDATA[SUCCESS]]></return_code></xml>";
            }
            return "<xml><return_code><![CDATA[fail]]></return_code></xml>";
        }
        /// <summary>
        /// 测试接口
        /// </summary>
        /// <param name="product_req"></param>
        /// <returns></returns>
        [Route("htl_test"), HttpPost, HttpGet, AllowAnonymous]
        public async Task<string> HtlTest([FromBody] htl_product_req product_req)
        {
            var order_req = new htl_order_req
            {
                order = product_req.products_xml
            };
            //var model = new htl_order_search_req {  start_time= "2018-09-01 10:27:50", end_time= "2018-09-06 10:27:50" };
            //var result = await _iHtlMallService.GetLogistics("20180905100402428336");
            //var result = await _iHtlMallService.GetOrdersInfo(model);
            //var model = new htl_req_base { };
            //var result = await _iHtlMallService.GetShippingInfo(model);
            //var result = await _iHtlMallService.OrderCancel("20180905100402428336","我不想买了");
            //var result = _iHtlMallService.UpdateCostPrice();
            //2018092511113211320579
            //var result = await _iHniaoService.GetGoodsListByCatId();

            var orders = new string[] { "2018101006354035404046", "201810100633023325119", "2018101006321132111008", "2018101005574757474905",
                                        "2018100922153915399933","2018100913315031501292","2018100912582058207979","2018100910341934190736" };
            foreach (var order_no in orders)
            {
                var result = await _iHtlMallService.PushOrderData(order_no);
            }
            return "";
        }
        /// <summary>
        /// 提供商品同步定时任务使用
        /// </summary>
        /// <returns></returns>
        [Route("htl_job"), HttpPost, HttpGet, AllowAnonymous]
        public string HtlJob()
        {
            lock (hf_nativeLock)
            {
                _iHtlMallService.AnalysisProducts();
                return "ok";
            }
        }
        /// <summary>
        /// 查询订单状态定时任务使用
        /// </summary>
        /// <returns></returns>
        [Route("htl_orders_status"), HttpPost, HttpGet, AllowAnonymous]
        public async Task<string> HtlOrderStatus()
        {
            //查询订单状态，更新数据库订单状态
            var result = await _iHtlMallService.GetOrderStatus();
            return "ok";
        }
        /// <summary>
        /// 推送订单定时任务使用
        /// </summary>
        /// <returns></returns>
        [Route("htl_push_order"), HttpPost, HttpGet, AllowAnonymous]
        public async Task<string> HtlPushOrder()
        {
            var result = await _iHtlMallService.PushOrder();
            return "ok";
        }
        /// <summary>
        /// 海淘乐后台推送
        /// </summary>
        /// <param name="order_no"></param>
        /// <returns></returns>
        [Route("htl_batch_push_order"), HttpPost, HttpGet, AllowAnonymous]
        public async Task<int> HtlBatchPushOrder(string orderNo)
        {
            var result = await _iHtlMallService.PushOrderData(orderNo);
            return result;
        }
        /// <summary>
        /// 推送候鸟订单定时任务使用
        /// </summary>
        /// <returns></returns>
        [Route("hniao_push_order"), HttpPost, HttpGet, AllowAnonymous]
        public async Task<string> HniaoPushOrder()
        {
            try
            {
                var result = await _iHniaoService.PushOrder();
            }
            catch (Exception ex)
            {

            }

            return "ok";
        }
        /// <summary>
        /// 批量推送候鸟订单
        /// </summary>
        /// <returns></returns>
        [Route("hniao_batch_push_order"), HttpPost, HttpGet, AllowAnonymous]
        public async Task<int> HniaoBatchPushOrder(string orderNo)
        {
            var result = await _iHniaoService.PushOrderBath(orderNo);
            return result;
        }
        /// <summary>
        /// 定时更新候鸟订单状态
        /// </summary>
        /// <returns></returns>
        [Route("hniao_order_status"), HttpPost, HttpGet, AllowAnonymous]
        public async Task<string> HniaoOrderStatus()
        {
            var result = await _iHniaoService.GetOrderStatus();
            return "ok";
        }
        /// <summary>
        /// 定时获取商品数据
        /// </summary>
        /// <param name="page"></param>
        /// <returns></returns>
        [Route("hniao_get_product"), HttpPost, HttpGet, AllowAnonymous]
        public async Task<string> HniaoGetProducts()
        {
            var result = await _iHniaoService.GetGoodsListByCatId();
            return "ok";
        }
        /// <summary>
        /// 手动同步候鸟数据
        /// </summary>
        /// <param name="tag"></param>
        /// <param name="sale_status"></param>
        /// <returns></returns>
        [Route("hniao_sync_product"), HttpPost, HttpGet, AllowAnonymous]
        public async Task<string> HniaoSyncProducts(string tag, int sale_status = 0)
        {
            var query = new GoodsQuery
            {
                tag = tag,
                sale_status = sale_status
            };
            var result = await _iProductService.GetProductSkus(query);
            return await Task.FromResult("ok");
        }
        /// <summary>
        /// 自动收货定时任务
        /// </summary>
        /// <returns></returns>
        [Route("auto_order_finish"), HttpPost, HttpGet, AllowAnonymous]
        public async Task<string> AutoOrderFinish()
        {
            var log = IocHelper.Get<ILogHelper>("info");
            log.Info("自动收货任务开始...");
            await _iOrderService.AutoOrderFinish();
            log.Info("自动收货任务开始...");
            return "ok";
        }
        /// <summary>
        /// 自动结算
        /// </summary>
        /// <returns></returns>
        [Route("auto_settle_accounts"), HttpPost, HttpGet, AllowAnonymous]
        public void AutoSettleAccounts()
        {
            var log = IocHelper.Get<ILogHelper>("info");
            log.Info("自动结算任务开始...");
            _iOrderService.AutoSettleAccount();
            log.Info("自动结算任务完成...");
        }
        // Three things to note in the signature:  
        //  - The method has an async modifier.   
        //  - The return type is Task or Task<T>. (See "Return Types" section.)  
        //    Here, it is Task<int> because the return statement returns an integer.  
        //  - The method name ends in "Async."  
        [Route("msdn"), HttpPost, HttpGet, AllowAnonymous]
        public async Task<int> AccessTheWebAsync()
        {
            var log = IocHelper.Get<ILogHelper>("info");
            log.Info("11111..." + System.Threading.Thread.CurrentThread.ManagedThreadId);
            // You need to add a reference to System.Net.Http to declare client.  
            HttpClient client = new HttpClient();

            // GetStringAsync returns a Task<string>. That means that when you await the  
            // task you'll get a string (urlContents).  
            //Task<string> getStringTask = client.GetStringAsync("https://msdn.microsoft.com");
            // You can do work here that doesn't rely on the string from GetStringAsync.  
            DoIndependentWork();

            // The await operator suspends AccessTheWebAsync.  
            //  - AccessTheWebAsync can't continue until getStringTask is complete.  
            //  - Meanwhile, control returns to the caller of AccessTheWebAsync.  
            //  - Control resumes here when getStringTask is complete.   
            //  - The await operator then retrieves the string result from getStringTask.  
            //string urlContents = await client.GetStringAsync("https://msdn.microsoft.com");
            int result = await MyAsync();
            log.Info("33333..." + System.Threading.Thread.CurrentThread.ManagedThreadId);
            // The return statement specifies an integer result.  
            // Any methods that are awaiting AccessTheWebAsync retrieve the length value.  
            return result;
        }

        private Task<int> MyAsync()
        {
            var log = IocHelper.Get<ILogHelper>("info");
            var t = new Task<int>((str) =>
            {
                var dt = DateTime.Now;
                Thread.Sleep(20000);
                log.Info("22222..." + System.Threading.Thread.CurrentThread.ManagedThreadId);
                return Thread.CurrentThread.ManagedThreadId;
            }, null);

            t.Start();

            return t;
        }

        private void DoIndependentWork() { }
        /// <summary>
        /// 后台人工自动解冻
        /// </summary>
        /// <param name="orderNo"></param>
        [Route("manul_settle_accounts"), HttpPost, HttpGet, AllowAnonymous]
        public void ManulSettleAccount(string orderNo)
        {
            _iOrderService.AutoSettleAccount(orderNo);
        }
    }
}